package cn.dengta.webapp.user.entity;

import java.util.Arrays;
import java.util.Date;
import javax.annotation.Nonnull;

import cn.dengta.common.model.*;
import cn.dengta.context.model.*;
import cn.dengta.webapp.base.entity.BizEntity;
import cn.dengta.webapp.base.entity.TimeBasedEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import me.codeplayer.util.StringUtil;
import me.codeplayer.util.X;

import static cn.dengta.context.model.UserEnumI18nKey.*;

/**
 * 用户操作审核表
 *
 * @author lgy
 * @since 2022-03-03
 */
@Setter
@Getter
@Accessors(chain = true)
public class OperateVerifyContent extends BizEntity {

	public static String RISK_TRUE = "机审通过";
	public static String RISK_FALSE = "机审不通过";

	/** 操作类型 */
	private OperateVerifyType type;
	/** 用户ID */
	private Long userId;
	/** 操作目标类型 */
	private String assocType;
	/** 操作目标ID */
	private Long assocId;
	/** 字段名称 */
	private String field;
	/** 原字段信息 */
	private String old;
	/** 新字段信息 */
	private String current;
	/** 备注信息 */
	private String remark;
	/** 初审审批人ID */
	private Long verifyUserId;
	/** 初审审批时间 */
	private Date verifyTime;
	/** 初审审批意见 */
	private String verifyRemark;
	/** 复审审批人ID */
	private Long reviewUserId;
	/** 复审审批时间 */
	private Date reviewTime;
	/** 复审审批意见 */
	private String reviewRemark;
	@TableField(exist = false)
	private User user;

	private transient Long channelId;

	public <T extends OperateVerifyContent> T init(OperateVerifyType type, Long userId, TimeBasedEntity entity, String field, String old, String current, String remark, Date now) {
		this.type = type;
		this.userId = userId;
		this.assocType = entity.entityName();
		this.assocId = entity.getId();
		this.field = field;
		this.old = StringUtil.toString(old);
		this.current = StringUtil.toString(current);
		this.remark = StringUtil.toString(remark);
		this.reviewRemark = StringUtil.toString(reviewRemark);
		this.verifyRemark = StringUtil.toString(verifyRemark);
		super.initTime(now);
		super.init(VerifyStatus.WAIT_VERIFY.value, State.PUBLIC);
		return X.castType(this);
	}

	public <T extends OperateVerifyContent> T init(OperateVerifyContent input, Date now) {
		this.type = input.type;
		this.userId = input.userId;
		this.assocType = input.assocType;
		this.assocId = input.assocId;
		this.field = input.field;
		this.old = StringUtil.toString(input.old);
		this.current = StringUtil.toString(input.current);
		this.remark = StringUtil.toString(remark);
		this.reviewRemark = StringUtil.toString(reviewRemark);
		this.verifyRemark = StringUtil.toString(verifyRemark);
		super.initTime(now);
		super.init(X.expectNotNull(input.getStatus(), VerifyStatus.WAIT_VERIFY.value), State.PUBLIC);
		return X.castType(this);
	}

	public <T extends OperateVerifyContent> T init(OperateVerifyType type, Long userId, TimeBasedEntity entity, String field, String remark, Date now) {
		return init(type, userId, entity, field, null, null, remark, now);
	}

	public boolean canVerify() {
		return VerifyStatus.WAIT_VERIFY.eq(status) && verifyUserId == null || VerifyStatus.VERIFY_TRUE.eq(status); // 初审通过允许重新审核
	}

	public boolean canReview() {
		return isSecondLevel() && VerifyStatus.WAIT_VERIFY.eq(status) && verifyUserId != null;
	}

	public boolean isFirstLevel() {
		return type.level == 1;
	}

	public boolean isSecondLevel() {
		return type.level == 2;
	}

	public void setId(Long id) {
		this.id = id;
	}

	@Getter
	public enum OperateVerifyType implements LabelI18nProxy<OperateVerifyType, Integer> {
		/** 头像 */
		AVATAR(0, VERIFY_TYPE_AVATAR, VERIFY_TYPE_AVATAR_DESC, 1),
		/** 动态 */
		MOMENT(1, VERIFY_TYPE_MOMENT, VERIFY_TYPE_MOMENT_DESC, 1),
		/** 相册 */
		PHOTO(2, VERIFY_TYPE_PHOTO, VERIFY_TYPE_PHOTO_DESC, 1),
		/** 实名认证 */
		REAL_NAME(3, VERIFY_TYPE_REAL_NAME, VERIFY_TYPE_REAL_NAME_DESC, 1),
		/** 真人认证 */
		FACE_AUTH(4, VERIFY_TYPE_FACE_AUTH, VERIFY_TYPE_FACE_AUTH_DESC, 1),
		/** 个人介绍 */
		SLOGAN(5, VERIFY_TYPE_SLOGAN, VERIFY_TYPE_SLOGAN_DESC, 1),
		/** 搭讪语 */
		GREET(6, VERIFY_TYPE_GREET, VERIFY_TYPE_GREET_DESC, 1),
		/** 相册视频 */
		PHOTO_VIDEO(7, VERIFY_TYPE_PHOTO, VERIFY_TYPE_PHOTO_DESC, 1),

		/** 昵称 */
		NICKNAME(8, UserFormI18nKey.USER_INFO_FORM_NICKNAME, UserFormI18nKey.USER_INFO_FORM_NICKNAME, 1),
		AI_AVATAR(9, UserFormI18nKey.AI_AVATAR, UserFormI18nKey.AI_AVATAR_DESC, 1),
		AI_STORY(10, UserFormI18nKey.AI_STORY, UserFormI18nKey.AI_STORY_DESC, 1),
		AI_OPEN_REMARKS(11, UserFormI18nKey.AI_OPEN_REMARKS, UserFormI18nKey.AI_OPEN_REMARKS_DESC, 1),

		/** 私人相册 */
		PRIVATE_PHOTO(12, VERIFY_TYPE_PRI_PHOTO, VERIFY_TYPE_PRI_PHOTO_DESC, 1),
		//
		;

		// 定义私有变量
		public final Integer value;
		public final String desc;
		/** 审核级别（目前只支持两级） */
		public final Integer level;
		public static final OperateVerifyType[] AI_CACHE = new OperateVerifyType[] { AI_AVATAR, AI_STORY, AI_OPEN_REMARKS };
		final ValueProxy<OperateVerifyType, Integer> proxy;

		// 构造函数，枚举类型只能为私有
		OperateVerifyType(Integer value, String label, String desc, Integer level) {
			this.value = value;
			this.level = level;
			this.desc = desc;
			this.proxy = new ValueProxy<>(this, value, label);
		}

		public String getI18nVerifyDesc(boolean yesOrNo, Language language, String remark) { // TODO 后续补上审核不通过原因
			String desc = getDesc(language);
			return language.msg(yesOrNo ? UserEnumI18nKey.VERIFY_TYPE_VERIFY_PASS : UserEnumI18nKey.VERIFY_TYPE_VERIFY_FAIL, desc);
		}

		public String getDesc(@Nonnull Language language) {
			return language.msg(getDesc());
		}

		public static OperateVerifyType[] getValues() {
			return ValueProxy.getCachedArray(OperateVerifyType.class, OperateVerifyType::values);
		}

		public static OperateVerifyType of(Integer value) {
			return AVATAR.getValueOf(value);
		}
	}

	public enum OperateVerifyStatus implements LabelI18nProxy<OperateVerifyStatus, Integer> {
		/** 用户取消 */
		CANCEL(-99, OPERATE_VERIFY_STATUS_CANCEL),
		/** 用户删除 */
		DELETE(-98, OPERATE_VERIFY_STATUS_DELETE),
		/** 审核不通过 */
		REVIEW_FALSE(-2, OPERATE_VERIFY_STATUS_REVIEW_FALSE, 2),
		/** 审核不通过 */
		VERIFY_FALSE(-1, OPERATE_VERIFY_STATUS_VERIFY_FALSE),
		/** 待审核 */
		WAIT_VERIFY(0, OPERATE_VERIFY_STATUS_WAIT_VERIFY),
		/** 审核通过 */
		VERIFY_TRUE(1, OPERATE_VERIFY_STATUS_VERIFY_TRUE),
		/** 审核通过 */
		REVIEW_TRUE(2, OPERATE_VERIFY_STATUS_REVIEW_TRUE, 2),
		/** 已完成 */
		COMPLETE(9, OPERATE_VERIFY_STATUS_COMPLETE, 2),
		//
		;

		public final Integer value;
		public final Integer verifyLevel;
		public final ValueProxy<OperateVerifyStatus, Integer> proxy;

		OperateVerifyStatus(Integer value, String label, Integer verifyLevel) {
			this.value = value;
			this.verifyLevel = verifyLevel;
			this.proxy = new ValueProxy<>(this, value, label);
		}

		OperateVerifyStatus(Integer value, String label) {
			this(value, label, 1);
		}

		public static OperateVerifyStatus[] getValues() {
			return ValueProxy.getCachedArray(OperateVerifyStatus.class, OperateVerifyStatus::values);
		}

		public static OperateVerifyStatus[] verifyValues;

		public static OperateVerifyStatus[] getVerifyValues() {
			OperateVerifyStatus[] verifies = verifyValues;
			if (verifies == null) {
				verifyValues = verifies = Arrays.stream(ValueProxy.getCachedAll(OperateVerifyStatus.class)).filter(c -> Status.asResult(c.verifyLevel)).toArray(OperateVerifyStatus[]::new);
			}
			return verifies;
		}

		public static OperateVerifyStatus of(Integer value) {
			return WAIT_VERIFY.getValueOf(value);
		}

		public static OperateVerifyStatus ofVerify(boolean yesOrNo) {
			return yesOrNo ? VERIFY_TRUE : VERIFY_FALSE;
		}

		@Override
		public ValueProxy<OperateVerifyStatus, Integer> getProxy() {
			return proxy;
		}
	}

	public static final String TYPE = "type";
	public static final String USER_ID = "user_id";
	public static final String ASSOC_TYPE = "assoc_type";
	public static final String ASSOC_ID = "assoc_id";
	public static final String FIELD = "field";
	public static final String OLD = "old";
	public static final String CURRENT = "current";
	public static final String REMARK = "remark";
	public static final String REVIEW_USER_ID = "review_user_id";
	public static final String REVIEW_TIME = "review_time";
	public static final String REVIEW_REMARK = "review_remark";
	public static final String VERIFY_USER_ID = "verify_user_id";
	public static final String VERIFY_TIME = "verify_time";
	public static final String VERIFY_REMARK = "verify_remark";

}
